﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;
using System.IO;

namespace GameServerpr4
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            InitBoard();
        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        TcpListener tcpListener;
        List<TcpClient> Clients = new List<TcpClient>();
        List<StreamWriter> WriteOut = new List<StreamWriter>();
        string[,] GameBoard = new string[3, 3];
        int Players;
        public static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            //Application.Run(new Form1());
            Form1 Game = new Form1();
            Game.Game_Server();

        }
        void Game_Server()
        {
            String IP = "127.0.0.1";
            int port = 9999;
            IPAddress address = IPAddress.Parse(IP);
            tcpListener = new TcpListener(address, port);
            tcpListener.Start();
            Players = 0;
            while (true)
            {
                TcpClient client = tcpListener.AcceptTcpClient();
                if (Players < 2)
                {
                    Players++;
                    Clients.Add(client);
                    Thread networkThread = new Thread(new ThreadStart(HandleNewClient));
                    networkThread.Start();
                }
                else
                {
                    Thread reject = new Thread(() => RejectNewClient(client));
                    reject.IsBackground = true;
                    reject.Start();
                }
            }
        }

        public void HandleNewClient()
        {
            TcpClient currentClient = Clients.Last();
            int playerNum;
            bool inGame = false;
            string piece = "";
            NetworkStream networkStream = currentClient.GetStream();
            System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(networkStream);
            System.IO.StreamReader streamReader = new System.IO.StreamReader(networkStream);
            WriteOut.Add(streamWriter);
            streamWriter.WriteLine("join = joined");
            streamReader.ReadLine();
            streamWriter.Flush();
            while (currentClient.Connected)
            {
                try
                {
                    while (Players != 2)
                    {
                        //Waiting loop
                    }
                    inGame = true;
                    playerNum = Clients.IndexOf(currentClient);
                    //Send the Players their piece
                    if (playerNum == 0)
                        piece = "x";
                    else
                        piece = "o";
                    InitBoard();
                    streamWriter.WriteLine("piece = " + piece);
                    streamWriter.WriteLine("turn = x");
                    streamWriter.Flush();
                    while (inGame)
                    {
                        if (Players != 2)
                        {
                            streamWriter.WriteLine("disconnect = yes");
                            streamWriter.Flush();
                            inGame = false;
                        }
                        else
                        {
                            string message = streamReader.ReadLine();
                            char[] delim = {' ','='};
                            string[] moveX = message.Split(delim,StringSplitOptions.RemoveEmptyEntries);
                            message = streamReader.ReadLine();
                            string[] moveY = message.Split(delim, StringSplitOptions.RemoveEmptyEntries);
                            message = streamReader.ReadLine();
                            string[] moveC = message.Split(delim, StringSplitOptions.RemoveEmptyEntries);
                            GameBoard[Convert.ToInt32(moveX[1]), Convert.ToInt32(moveY[1])] = moveC[1];
                            string winner = isThereAWinner();
                            string turn = whoIsNext(moveC[1]);
                            foreach (StreamWriter sw in WriteOut)
                            {
                                sw.WriteLine("xindex = " + moveX[1]);
                                sw.WriteLine("yindex = " + moveY[1]);
                                sw.WriteLine("char = " + moveC[1]);
                                if (winner != "g")
                                {
                                    sw.WriteLine("outcome = " + winner);
                                    inGame = false;
                                }
                                else
                                    sw.WriteLine("turn = " + turn);
                                sw.Flush();
                            }

                        }
                    }
                }
                catch (Exception)
                {
                    Clients.Remove(currentClient);
                    WriteOut.Remove(streamWriter);
                    foreach (StreamWriter sw in WriteOut)
                    {
                        sw.WriteLine("disconnect = yes");
                        sw.Flush();
                    }
                    streamWriter.Close();
                    streamReader.Close();
                    networkStream.Close();
                    Players--;
                }
            }
        }
        //Reject client above the second one.
        public void RejectNewClient(TcpClient client)
        {
            NetworkStream networkStream = client.GetStream();
            System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(networkStream);
            System.IO.StreamReader streamReader = new System.IO.StreamReader(networkStream);
            streamWriter.WriteLine("join = rejected");
            streamWriter.Flush();
            streamWriter.Close();
            streamReader.Close();
            networkStream.Close();
        }
        public void InitBoard()
        {
            for (int x = 0; x < 3; x++)
            {
                for (int y = 0; y < 3; y++)
                {
                    GameBoard[x, y] = "g";
                }
            }
        }
        public string isThereAWinner()
        {
            //Row Wins
            if ((GameBoard[0, 0] == GameBoard[0, 1]) && (GameBoard[0, 1] == GameBoard[0, 2]) && (GameBoard[0, 2] != "g"))
                return GameBoard[0, 0];
            if ((GameBoard[1, 0] == GameBoard[1, 1]) && (GameBoard[1, 1] == GameBoard[1, 2]) && (GameBoard[0, 2] != "g"))
                return GameBoard[1, 0];
            if ((GameBoard[2, 0] == GameBoard[2, 1]) && (GameBoard[2, 1] == GameBoard[2, 2]) && (GameBoard[0, 2] != "g"))
                return GameBoard[2, 0];
            //Column Wins
            if ((GameBoard[0, 0] == GameBoard[1, 0]) && (GameBoard[1, 0] == GameBoard[2, 0]) && (GameBoard[0, 2] != "g"))
                return GameBoard[0, 0];
            if ((GameBoard[0, 1] == GameBoard[1, 1]) && (GameBoard[1, 1] == GameBoard[2, 1]) && (GameBoard[0, 2] != "g"))
                return GameBoard[0, 1];
            if ((GameBoard[0, 2] == GameBoard[1, 2]) && (GameBoard[1, 2] == GameBoard[2, 2]) && (GameBoard[0, 2] != "g"))
                return GameBoard[0, 2];
            //Diagonal Wins
            if ((GameBoard[0, 0] == GameBoard[1, 1]) && (GameBoard[1, 1] == GameBoard[2, 2]) && (GameBoard[0, 2] != "g"))
                return GameBoard[0, 0];
            if ((GameBoard[0, 2] == GameBoard[1, 1]) && (GameBoard[1, 1] == GameBoard[2, 0]) && (GameBoard[0, 2] != "g"))
                return GameBoard[0, 2];
            //Tie Game
            if ((GameBoard[0, 0] != "g") && (GameBoard[0, 1] != "g") && (GameBoard[0, 2] != "g") && (GameBoard[1, 0] != "g") && (GameBoard[1, 1] != "g") &&
                (GameBoard[1, 2] != "g") && (GameBoard[2, 0] != "g") && (GameBoard[2, 1] != "g") && (GameBoard[2, 2] != "g"))
                return "t";
            return "g";
        }
        public string whoIsNext(string c)
        {
            if (c == "x")
                return "o";
            else
                return "x";
        }
    }
}
